﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<memory>

using namespace std;

//// 智能指针 代管资源，而不是拥有资源
//// 模拟指针的行为，访问修改资源
//// 应该是浅拷贝，那就有析构多次的问题
//struct Date
//{
//	int _year;
//	int _month;
//	int _day;
//
//	Date(int year = 1, int month = 1, int day = 1)
//		:_year(year)
//		, _month(month)
//		, _day(day)
//	{}
//
//	~Date()
//	{
//		cout << "~Date()" << endl;
//	}
//};
//
//int main()
//{
//	auto_ptr<Date> ap1(new Date);
//	// 拷⻉时，管理权限转移，被拷⻉对象 ap1 悬空 
//	auto_ptr<Date> ap2(ap1);
//	// 空指针访问，ap1 对象已经悬空 
//	// ap1->_year++;// 报错
//
//	unique_ptr<Date> up1(new Date);
//	// 不⽀持拷⻉ 
//	// unique_ptr<Date> up2(up1);
//	// ⽀持移动，但是移动后 up1 也悬空，所以使⽤移动要谨慎 
//	unique_ptr<Date> up3(move(up1));
//
//	shared_ptr<Date> sp1(new Date);
//	// ⽀持拷贝
//	shared_ptr<Date> sp2(sp1);
//	shared_ptr<Date> sp3(sp2);
//	cout << sp1.use_count() << endl;// 3
//	sp1->_year++;
//	cout << sp1->_year << endl;// 2
//	cout << sp2->_year << endl;// 2
//	cout << sp3->_year << endl;// 2
//	// ⽀持移动，但是移动后 sp1 也悬空，所以使⽤移动要谨慎 
//	shared_ptr<Date> sp4(move(sp1));
//
//	return 0;
//}

struct Date
{
	int _year;
	int _month;
	int _day;

	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		cout << "~Date()" << endl;
	}
};

//namespace zgx
//{
//	// 引用计数的本质，一块资源对应多少个智能指针对象的管理
//	// 不能用static来引用计数
//	template<class T>
//	class shared_ptr
//	{
//	public:
//		shared_ptr(T* ptr)
//			:_ptr(ptr)
//			, _pcount(new int(1))
//		{}
//
//		shared_ptr(const shared_ptr<T>& sp)
//			:_ptr(sp._ptr)
//			, _pcount(sp._pcount)
//		{
//			(*_pcount)++;
//		}
//
//		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
//		{
//			// 智能指针自己赋值自己有两种
//			// 1.sp4 = sp4
//			// 2.sp1 = sp2
//			//if (*this != sp)
//			if(_ptr != sp._ptr)
//			{
//				if (--(*_pcount) == 0)
//				{
//					delete _ptr;
//					delete _pcount;
//				}
//				_ptr = sp._ptr;
//				_pcount = sp._pcount;
//				++(*_pcount);
//			}
//			return *this;
//		}
//
//		~shared_ptr()
//		{
//			if (--(*_pcount) == 0)
//			{
//				delete _ptr;
//				delete _pcount;
//			}
//		}
//
//		T& operator*()
//		{
//			return *_ptr;
//		}
//
//		T* operator->()
//		{
//			return _ptr;
//		}
//
//	private:
//		T* _ptr;
//		int* _pcount;
//	};
//}

//int main()
//{
//	zgx::shared_ptr<Date> sp1(new Date);
//	zgx::shared_ptr<Date> sp2(sp1);
//	zgx::shared_ptr<Date> sp3(sp2);
//	zgx::shared_ptr<Date> sp4(new Date);
//	return 0;
//}

//template<class T>
//void DeleteArrayFunc(T* ptr)
//{
//	delete[] ptr;
//}
//
//class Fclose
//{
//public:
//	void operator()(FILE* ptr)
//	{
//		cout << "fclose:" << ptr << endl;
//		fclose(ptr);
//	}
//};
//
//
//int main()
//{
//	std::shared_ptr<Date> sp1(new Date);
//	// 特化
//	std::shared_ptr<Date[]> sp2(new Date[10]);
//	// lambda表达式
//	std::shared_ptr<Date> sp3(new Date[10], [](Date* ptr) {
//		delete[] ptr;
//		});
//
//	// 函数模版的可调用对象要加<>
//	std::shared_ptr<Date> sp4(new Date[10], DeleteArrayFunc<Date>);
//
//	// 定制删除器（传递可调用对象）
//	std::shared_ptr<FILE> sp4(fopen("Test.cpp", "r"), [](FILE* ptr) {
//		cout << "fclose:" << ptr << endl;
//		fclose(ptr);
//		});
//
//	std::unique_ptr<Date> up1(new Date);
//	std::unique_ptr<Date[]> up2(new Date[10]);
//
//	// unique_ptr 定制删除器 建议传仿函数
//	std::unique_ptr<FILE, Fclose> up3(fopen("Test.cpp", "r"));
//
//	auto fcloseFunc = [](FILE* ptr) {
//		cout << "fclose:" << ptr << endl;
//		fclose(ptr);
//		};
//	// decltype 推导类型
//	std::unique_ptr<FILE, decltype(fcloseFunc)> up4(fopen("Test.cpp", "r"), fcloseFunc);
//
//	return 0;
//}

//int main()
//{
//	std::shared_ptr<Date> sp1(new Date(2025, 11, 15));
//
//	// make_shared(把引用计数和对象开到一起)
//	std::shared_ptr<Date> sp2 = make_shared<Date>(2025, 11, 15);
//
//	// ⽀持了operatorbool的类型转换，如果智能指针对象是⼀个
//	// 空对象没有管理资源，则返回false，否则返回true
//
//	return 0;
//}

//int main()
//{
//	shared_ptr<Date> sp1(new Date(2024, 9, 11));
//
//	shared_ptr<Date> sp2 = make_shared<Date>(2024, 9, 11);
//
//	auto sp3 = make_shared<Date>(2024, 9, 11);
//
//	shared_ptr<Date> sp4;
//
//	// if (sp1.operator bool())
//	// 自定义类型转换成 bool 类型（做条件逻辑判断）
//	if (sp1)
//		cout << "sp1 is not nullptr" << endl;
//	if (!sp4)
//		cout << "sp1 is nullptr" << endl;
//
//	// 报错 
//	// 构造函数都使⽤ explicit 修饰，防⽌ 普通指针 隐式类型转换成 智能指针 对象
//	// shared_ptr<Date> sp5 = new Date(2024, 9, 11);
//	// unique_ptr<Date> sp6 = new Date(2024, 9, 11);
//
//	return 0;
//}

struct ListNode
{
	int _data;
	std::shared_ptr<ListNode> _next;
	std::shared_ptr<ListNode> _prev;

	// 这⾥改成 weak_ptr ，当 n1->_next = n2; 绑定shared_ptr时 
	// 不增加 n2 的引⽤计数，不参与 资源释放的管理，就不会形成循环引⽤了 
	/*std::weak_ptr<ListNode> _next;
	std::weak_ptr<ListNode> _prev;*/
	~ListNode()
	{
		cout << "~ListNode()" << endl;
	}
};

int main()
{
	// 循环引⽤ -- 内存泄露 
	std::shared_ptr<ListNode> n1(new ListNode);
	std::shared_ptr<ListNode> n2(new ListNode);

	cout << n1.use_count() << endl;// 1
	cout << n2.use_count() << endl;// 1

	// 智能指针的赋值重载 ↓
	// 将 shared_ptr 赋值给 weak_ptr
	n1->_next = n2;
	n2->_prev = n1;

	cout << n1.use_count() << endl;// 2
	cout << n2.use_count() << endl;// 2

	// weak_ptr 不⽀持管理资源，不⽀持 RAII 
	// weak_ptr 是专门绑定 shared_ptr，不增加他的 引⽤计数，作为⼀些场景的 辅助管理 
	//std::weak_ptr<ListNode> wp(new ListNode);
	return 0;
}

